import deepMerge from "../function/deepMerge";
import validate from "../function/test";
import store  from '../../../store/index'
class Request {
  // 设置全局默认配置
  setConfig (customConfig) {
    // 深度合并对象，否则会造成对象深层属性丢失
    this.config = deepMerge(this.config, customConfig);
  }

  // 主要请求部分
  request (options = {}) {
    let userAccount = uni.getStorageSync('userAccount')
    // 检查请求拦截
    if (this.interceptor.request && typeof this.interceptor.request === 'function') {
      let tmpConfig = {};
      let interceptorRequest = this.interceptor.request(options);
      if (interceptorRequest === false) {
        // 返回一个处于pending状态中的Promise，来取消原promise，避免进入then()回调
        return new Promise(() => { });
      }
      this.options = interceptorRequest;
    }
    options.dataType = options.dataType || this.config.dataType;
    options.responseType = options.responseType || this.config.responseType;
    options.url = options.url || '';
    options.params = options.params || {};
    options.header = Object.assign(this.config.header, options.header);
    options.header.accessToken = userAccount || undefined
    if (userAccount) {
      options.header.equipment = 'app'
    }
    options.method = options.method || this.config.method;
    if (uni.getStorageSync('Appuuid')) {
      options.header.Appuuid = uni.getStorageSync('Appuuid')
    }
    return new Promise((resolve, reject) => {
      options.complete = (response) => {
        // 请求返回后，隐藏loading(如果请求返回快的话，可能会没有loading)
        uni.hideLoading();

        // 清除定时器，如果请求回来了，就无需loading
        clearTimeout(this.config.timer);
        this.config.timer = null;
        // 判断用户对拦截返回数据的要求，如果originalData为true，返回所有的数据(response)到拦截器，否则只返回response.data
        if (this.config.originalData) {
          // 判断是否存在拦截器
          if (this.interceptor.response && typeof this.interceptor.response === 'function') {
            let resInterceptors = this.interceptor.response(response);
            // 如果拦截器不返回false，就将拦截器返回的内容给this.$u.post的then回调
            if (resInterceptors !== false) {
              resolve(resInterceptors);
            } else {
              // 如果拦截器返回false，意味着拦截器定义者认为返回有问题，直接接入catch回调
              reject(response);
            }
          } else {
            // 如果要求返回原始数据，就算没有拦截器，也返回最原始的数据
            resolve(response);
          }
        } else {
          if (response.statusCode == 200) {
            if (this.interceptor.response && typeof this.interceptor.response === 'function') {
              let resInterceptors = this.interceptor.response(response.data);
              if (resInterceptors !== false) {
                resolve(resInterceptors);
              } else {
                if (response.data.code == '10025') {
                  uni.removeStorage({
                    key: 'userAccount'
                  })
                  uni.removeStorage({
                    key: 'userInfo'
                  })
                  uni.removeStorage({
                    key: 'accountId'
                  })
                  uni.reLaunch({
                    url: '/pages/login/login',
                  })
                } else if (response.data.code == '20001') {
                  if (userAccount) {
                    uni.showModal({
                      title: '提示',
                      content: response.data.message,
                      success: function (res) {
                        if (res.confirm) {
                          uni.reLaunch({
                            url: '/pages/login/login',
                          })
                        } else if (res.cancel) {
                          console.log('用户点击取消');
                        }
                      }
                    });
                  }
                } else if (response.data.code == '20003') {
                  uni.showToast({
                    title: response.data.message,
                    duration: 2000,
                    icon: 'none'
                  })
                  setTimeout(() => {
                    store.commit('logout')
                  }, 2000);
                } else {
                  reject(response.data);
                }
              }
            } else {
              // 如果不是返回原始数据(originalData=false)，且没有拦截器的情况下，返回纯数据给then回调
              // 统一处理是否登录
              if (response.data.code == '10025') {
                uni.removeStorage({
                  key: 'userAccount'
                })
                uni.removeStorage({
                  key: 'userInfo'
                })
                uni.removeStorage({
                  key: 'accountId'
                })
                uni.reLaunch({
                  url: '/pages/login/login',
                })
              } else if (response.data.code == '20001') {
                if (userAccount) {

                  uni.showModal({
                    title: '提示',
                    content: response.data.message,
                    success: function (res) {
                      if (res.confirm) {
                        uni.reLaunch({
                          url: '/pages/login/login',
                        })
                      } else if (res.cancel) {
                        console.log('用户点击取消');
                      }
                    }
                  });
                }
              } else if (response.data.code == '20003') {
                uni.showToast({
                    title: response.data.message,
                    duration: 2000,
                    icon: 'none'
                  })
                  setTimeout(() => {
                    store.commit('logout')
                  }, 2000);
                }
              else {
                resolve(response.data);
              }
            }
          } else {
            // 不返回原始数据的情况下，服务器状态码不为200，modal弹框提示
            // if(response.errMsg) {
            // 	uni.showModal({
            // 		title: response.errMsg
            // 	});
            // }
            reject(response)
          }
        }
      }

      // 判断用户传递的URL是否/开头,如果不是,加上/，这里使用了uView的test.js验证库的url()方法
      options.url = validate.url(options.url) ? options.url : (this.config.baseUrl + (options.url.indexOf('/') == 0 ?
        options.url : '/' + options.url));

      // 是否显示loading
      // 加一个是否已有timer定时器的判断，否则有两个同时请求的时候，后者会清除前者的定时器id
      // 而没有清除前者的定时器，导致前者超时，一直显示loading
      if (this.config.showLoading && !this.config.timer) {
        this.config.timer = setTimeout(() => {
          uni.showLoading({
            title: this.config.loadingText,
            mask: this.config.loadingMask
          })
          this.config.timer = null;
        }, this.config.loadingTime);
      }
      uni.request(options);
    })
    // .catch(res => {
    // 	// 如果返回reject()，不让其进入this.$u.post().then().catch()后面的catct()
    // 	// 因为很多人都会忘了写后面的catch()，导致报错捕获不到catch
    // 	return new Promise(()=>{});
    // })
  }

  constructor() {
    this.config = {
      baseUrl: '', // 请求的根域名
      // 默认的请求头
      header: {},
      method: 'POST',
      // 设置为json，返回后uni.request会对数据进行一次JSON.parse
      dataType: 'json',
      // 此参数无需处理，因为5+和支付宝小程序不支持，默认为text即可
      responseType: 'text',
      showLoading: true, // 是否显示请求中的loading
      loadingText: '请求中...',
      loadingTime: 800, // 在此时间内，请求还没回来的话，就显示加载中动画，单位ms
      timer: null, // 定时器
      originalData: false, // 是否在拦截器中返回服务端的原始数据，见文档说明
      loadingMask: true, // 展示loading的时候，是否给一个透明的蒙层，防止触摸穿透
    }

    // 拦截器
    this.interceptor = {
      // 请求前的拦截
      request: null,
      // 请求后的拦截
      response: null
    }

    // get请求
    this.get = (url, data = {}, header = {}) => {
      return this.request({
        method: 'GET',
        url,
        header,
        data
      })
    }

    // post请求
    this.post = (url, data = {}, header = { 'content-type': 'application/json', }) => {
      return this.request({
        url,
        method: 'POST',
        header,
        data
      })
    }

    // put请求，不支持支付宝小程序(HX2.6.15)
    this.put = (url, data = {}, header = {}) => {
      return this.request({
        url,
        method: 'PUT',
        header,
        data
      })
    }

    // delete请求，不支持支付宝和头条小程序(HX2.6.15)
    this.delete = (url, data = {}, header = {}) => {
      return this.request({
        url,
        method: 'DELETE',
        header,
        data
      })
    }
  }
}
export default new Request
